/*
 *  Copyright (c) 2018, Infineon Technologies AG
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification,are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holders nor the names of its contributors
 *  may be used to endorse or promote products derived from this software without
 *  specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 *  To improve the quality of the software, users are encouraged to share
 *  modifications, enhancements or bug fixes with Infineon Technologies AG
 *  dave@infineon.com).
 */
/**
 * \defgroup controller Controller
 * @{
 */
/**
 * \file    controller.h
 * \author  Manuel Escudero Rodriguez
 * \date    09.05.2018
 * \brief   Controller code
 */
#ifndef __CONTROLLER_H_
#define __CONTROLLER_H_

#include <stdbool.h>
#include <xmc4200.h>
#include <xmc_hrpwm.h>
#include <xmc_gpio.h>
#include "communication.h"
#include "config_pwm.h"
#include "config_adc.h"

/**
 * \name LEDs
 * Blinking LEDs configuration.
 * @{
 */
/** Switching speed of LEDs. [control_cyc/2^LEDS_SPEED] */
#define LEDS_SPEED		(16)
/** MACRO. Switch OFF red LED. */
#define RED_LED_RST()   (((XMC_GPIO_PORT_t *) PORT0_BASE)->OMR = 0x10000UL << 10u)
/** MACRO. Toggle red LED. */
#define RED_LED_TGL()   (((XMC_GPIO_PORT_t *) PORT0_BASE)->OMR = 0x10001UL << 10u)
/** MACRO. Switch ON red LED. */
#define RED_LED_SET()   (((XMC_GPIO_PORT_t *) PORT0_BASE)->OMR = (uint32_t)1U << 10u)
/** MACRO. Checks red LED status. */
#define RED_LED_ON      ((((XMC_GPIO_PORT_t *) PORT0_BASE)->IN >> 10u) & (uint32_t) 1u)
/** MACRO. Switch OFF blue LED. */
#define BLUE_LED_RST()  (((XMC_GPIO_PORT_t *) PORT0_BASE)->OMR = 0x10000UL << 1u)
/** MACRO. Toggle blue LED. */
#define BLUE_LED_TGL()  (((XMC_GPIO_PORT_t *) PORT0_BASE)->OMR = 0x10001UL << 1u)
/** MACRO. Switch ON blue LED. */
#define BLUE_LED_SET()  (((XMC_GPIO_PORT_t *) PORT0_BASE)->OMR = (uint32_t)1U << 1u)
/** MACRO. Checks blue LED status. */
#define BLUE_LED_ON     ((((XMC_GPIO_PORT_t *) PORT0_BASE)->IN >> 1u) & (uint32_t) 1u)
/** @} */

/**
 * \defgroup control_features Controller features
 * @{
 */
/**
 * \name Mode
 * Converter mode configuration.
 * @{
 */
#define IO_BOOST_MODE	((((XMC_GPIO_PORT_t *) PORT2_BASE)->IN >> 7u) & (uint32_t) 1u)
/** @} */

/**
 * \name Buck phase limits
 * Phase shift limits during regulation.
 * @{
 */
/** Maximum possible phase overlap of PWM modulation. [CCU_clock] */
#define MAX_PHASE           	(PWM_A_B_DUTY - PWM_CHAIN_DLY_A_D) // (400-7) = 393
/** Minimum allowed phase overlap of buck regulation. [CCU_clock] */
#define BUCK_PHASE_MIN          (parameters_RAM.min_phase)
/** Limitation of maximum phase overlap to allow reset time of current sense. [CCU_clock] */
#define PHASE_MARGIN			(5)
/** Maximum allowed phase overlap of PWM modulation in buck mode. [CCU_clock] */
#define MAX_ADJ_PHASE  			(MAX_PHASE - PHASE_MARGIN) // (393 - 5) = 388
/** @} */

/**
 * \name Boost duty limits
 * Duty limits during regulation.
 * @{
 */
/** Minimum reference value generated by the high resolution DACs. [DAC_units] */
#define BOOST_PWM_DTY_ABS_MAX	(MAX_ADJ_PHASE + 8) // (388 + 8) = 396
/** Minimum reference value generated by the high resolution DACs. [DAC_units] */
#define BOOST_PWM_DTY_MAX		(BOOST_PWM_DTY_ABS_MAX - 200)//(BOOST_PWM_DTY_ABS_MAX - 100)
/** Maximum phase of bridge PWM in boost mode modulation. */
#define BOOST_PWM_PHASE_MAX		(BOOST_PWM_DTY_ABS_MAX - current_ctr.dt_C_D + 16) // (BOOST_PWM_DTY_ABS_MAX - current_ctr.dt_C_D - 3) corresponds to zero precharge
/** Minimum allowed phase overlap in boost mode. [CCU_clock] */
#define BOOST_PHASE_MIN  		(100)
/** Minimum duty of boost converter PWM (synchronous FETs). [CCU_clock] */
#define BOOST_PWM_DTY_MIN   	(0)
#if (BOOST_PWM_DTY_MIN < 0)
	#error "BOOST_PWM_PHASE_MIN should be positive or zero (see comparisons in code)"
#endif
/** Minimum duty to apply while turning OFF. [CCU_clock] */
#define BOOST_OFF_DTY          	(BOOST_PWM_DTY_MIN + 25)
#if !(BOOST_OFF_DTY >= BOOST_MIN_DTY)
	#error "BOOST_OFF_DTY should equal or bigger than BOOST_MIN_DTY(see comparisons in code)"
#endif
/** Extra base precharge during dead time. */
#define BOOST_STRTP_XTRA_PRCHRG	(4)
/** Precharging adaptation factor threshold. [CCU_clk] */
#define BOOST_PRCHRG_THRSLD		(550) // (610)
/** Precharging time factor related to resonant inductance. [CCU_clock] */
#define BOOST_PRCHRG_LR_LOW     (3) // Precharging coefficient at low loads    
/** Precharging time factor related to resonant inductance. [CCU_clock] */
#define BOOST_PRCHRG_LR_HIGH    (4)//(3) // Precharging additional coefficient at high loads 
/** Fixed point format of coefficients. [bits] */
#define PRCHRG_Q_DECIMALS  		(8)
/** Precharging adaptation delay. [control_cyc] */
#define BOOST_STRTP_PHASE_ADJST_DLY		(5)
/** Precharging adaptation threshold. [CCU_clk] */
#define BOOST_STRTP_PHASE_ADJST_THRSLD	(1)
/** Precharging adaptation delay. [control_cyc] */
#define BOOST_PHASE_ADJST_DLY			(40)
/** Precharging adaptation threshold. [CCU_clk] */
#define BOOST_PHASE_ADJST_THRSLD		(2)
/** @} */

/**
 * \name Burst management
 * Frequency limited burst configuration.
 * @{
 */
/** Number of cycles skipped during burst mode. Fburst_max = (Burst_trap_cyc / (Burst_trap_cyc + Burst_lenght_cyc) * Control_frequency. [control_cyc] */
#define BURST_TRAP_CYC      		(parameters_RAM.burst_trap_cyc)
/** Number of cycles applied during burst mode. Fburst_max = (Burst_trap_cyc / (Burst_trap_cyc + Burst_lenght_cyc) * Control_frequency. [control_cyc] */
#define BURST_PULSE_CYC				(parameters_RAM.burst_lenght)
/** Burst mode entrance condition filter. [control_cyc] */
#define BURST_IN_CYC        		(1)
/** Burst mode exit condition filter. [control_cyc] */
#define BURST_OUT_CYC       		(1)
/** Minimum phase applied during burst mode. [CCU_clock] */
#define BUCK_BURST_PHASE     		(parameters_RAM.burst_phase)
/** If compensator output falls below this limit the converter stops switching. [CCU_clock] */
#define BUCK_BURST_STOP_LIMIT		(parameters_RAM.burst_stop_limit)
/** Burst mode activation limit. [CCU_clock] */
#define BUCK_BURST_LOW_LIMIT  		(parameters_RAM.burst_low_limit)
/** Burst mode deactivation limit. [CCU_clock] */
#define BUCK_BURST_HIGH_LIMIT  		(parameters_RAM.burst_high_limit)
/** @} */

/**
 * \defgroup protections Protections
 * @{
 */
/**
 * \name Brown in, brown out
 * Hysteresis windows for brown in and brown out.
 * The 350V level can be adjusted and the rest of levels calculated from that.
 * Note: Will be inaccurate if the gain of the Vin measurement is not fixed.
 * @{
 */
/** Filtering ratio of the input current average value.  average_il = (average_il * factor + il) / (2^ratio)  */
#define ADC_VIN_AVG_RATIO	(6)
/** Filtering factor of the input current average value. average_il = (average_il * factor + il) / (2^ratio) */
#define ADC_VIN_AVG_FACTOR	((1 << ADC_VIN_AVG_RATIO) - 1)
/** Filtering ratio of the input current average value.  average_il = (average_il * factor + il) / (2^ratio)  */
#define ADC_VO_AVG_RATIO	(6)
/** Filtering factor of the input current average value. average_il = (average_il * factor + il) / (2^ratio) */
#define ADC_VO_AVG_FACTOR	((1 << ADC_VO_AVG_RATIO) - 1)
/** Input voltage is rising from below the low limit. */
#define V_RISING          	(0)
/** Input voltage is falling from above the high limit. */
#define V_FALLING         	(1)
/** Minimum input voltage, upper threshold. Around 375V. [ADC_units] */
#define VIN_MIN_HIGH        (parameters_RAM.vin_min_high)
/** Minimum input voltage, lower threshold. Around 350V. [ADC_units] */
#define VIN_MIN_LOW         (VIN_MIN_HIGH - 658)
/** Maximum input voltage, lower threshold. Around 400V. [ADC_units] */
#define VIN_MAX_LOW         (VIN_MIN_HIGH + 658)
/** Maximum input voltage, upper threshold. Around 415V. [ADC_units] */
#define VIN_MAX_HIGH        (VIN_MIN_HIGH + 1053 +103)

/** Minimum input voltage, upper threshold. Around 375V. [ADC_units] */
#define BOOST_VIN_MIN_HIGH	(8757)//(8757-500*5)-->300V//250v // Approx. 326V
/** Minimum input voltage, lower threshold. Around 350V. [ADC_units] */
#define BOOST_VIN_MIN_LOW	(BOOST_VIN_MIN_HIGH - 250) // Approx. 10V less.
/** Maximum input voltage, upper threshold. Around 415V. [ADC_units] */
#define BOOST_VIN_MAX_HIGH	(9500)//(10020) // Approx. 373V
/** Maximum input voltage, lower threshold. Around 400V. [ADC_units] */
#define BOOST_VIN_MAX_LOW	(BOOST_VIN_MAX_HIGH - 250) // Approx. 10V less.
#if (BOOST_VIN_MIN_HIGH >= BOOST_VIN_MAX_LOW)
	#error "BOOST_VIN_MIN_HIGH should be higher than BOOST_VIN_MAX_LOW"
#endif
/** Minimum input voltage, lower threshold. Around 350V. [ADC_units] */
#define BOOST_VO_MIN_HIGH 	(11333) // Approx. 43V
/** Minimum input voltage, lower threshold. Around 350V. [ADC_units] */
#define BOOST_VO_DTY_BASE 	(11333) // (11860) // Approx. 45V
/** Minimum input voltage, lower threshold. Around 350V. [ADC_units] */
#define BOOST_VO_MIN_LOW 	(BOOST_VO_MIN_HIGH - 263*1)//(BOOST_VO_MIN_HIGH - 263*3) // Approx. 1V less
/** Maximum input voltage, upper threshold. Around 415V. [ADC_units] */
#define BOOST_VO_MAX_HIGH  	(15155) // Approx. 57.5V
/** Maximum input voltage, upper threshold. Around 415V. [ADC_units] */
#define BOOST_VO_MAX_LOW  	(BOOST_VO_MAX_HIGH - 263) // Approx. 1V less
/** Maximum input voltage, lower threshold. Around 400V. [ADC_units] */
#define BOOST_VIN_MIN       (BOOST_VOLTAGE_REF - 390) // Approx. 15V less
/** Maximum input voltage, upper threshold. Around 415V. [ADC_units] */
#define BOOST_VIN_MAX       (BOOST_VOLTAGE_REF + 390) // Approx. 15V more
/** Clock division of Vo stability check. [power of 2] */
#define V_STBLTY_CLK_DIV	(9)
/** Clock division of Vo stability check. [units] */
#define V_STBLTY_CNT		(10)
/** Margin of variation before starting up. [ADC_units] */
#define VO_STBLTY_MARGIN	(50)
/** Margin of variation before starting up. [ADC_units] */
#define VIN_STBLTY_MARGIN	(132) // Approx. 5V
/** @} */

/**
 * \name Hiccup
 * Over current protection based in turning off and starting up retrial.
 * Note: Only input current is measured. Scalation has to be done based in 
 * input voltage to trigger the overcurrent at same power for all range.
 * @{
 */
/** Filtering ratio of the input current average value.  average_il = (average_il * factor + il) / (2^ratio)  */
#define ADC_IL_AVG_RATIO		(1)	
/** Filtering factor of the input current average value. average_il = (average_il * factor + il) / (2^ratio) */
#define ADC_IL_AVG_FACTOR		(1)
#if ADC_IL_AVG_FACTOR != ((1 << ADC_IL_AVG_RATIO) - 1)
	#error "ADC_IL_AVG_FACTOR should be ((1 << ADC_IL_AVG_RATIO) - 1)"
#endif
/** Filtering ratio of the input current average value.  average_il = (average_il * factor + il) / (2^ratio)  */
#define ADC_IO_AVG_RATIO		(1)
/** Filtering factor of the input current average value. average_il = (average_il * factor + il) / (2^ratio) */
#define ADC_IO_AVG_FACTOR		(1)
#if ADC_IO_AVG_FACTOR != ((1 << ADC_IO_AVG_RATIO) - 1)
	#error "ADC_IO_AVG_FACTOR should be ((1 << ADC_IO_AVG_RATIO) - 1)"
#endif
/** Filtering ratio of the input current average value.  average_il = (average_il * factor + il) / (2^ratio)  */
#define ADC_IO_ZERO_RATIO		(1)
/** Filtering factor of the input current average value. average_il = (average_il * factor + il) / (2^ratio) */
#define ADC_IO_ZERO_FACTOR		((1 << ADC_IO_ZERO_RATIO) - 1)
#if ADC_IO_ZERO_FACTOR != ((1 << ADC_IO_ZERO_RATIO) - 1)
	#error "ADC_IO_AVG_FACTOR should be ((1 << ADC_IO_AVG_RATIO) - 1)"
#endif
/** Current limit during soft start for entering HICCUP mode. [ADC_units] */
#define HICCUP_SOFT_LIM     	(3750) // Aprox. 85 A
/** Current limit in normal mode for entering HICCUP. [ADC_units] */
#define HICCUP_LIM          	(3750) // Aprox. 85 A
/** Hiccup detection filter. [control_cyc] */
#define HICCUP_IN_CNT_LIM  	 	(100)
/** Hiccup soft-start retry delay time. [control_cyc] */
#define HICCUP_OUT_CNT_LIM  	(100000)
/** Over power limit. [ADC_units] */
#define OVPWR_LIM     			(19029336)//-->1600w（实际SMPS对应1000w）(2378667)//(3378667)//-->280W(2378667)//-->200w(39248000)//(38653000) // Aprox. 3300W（39248000）
/** Over power limit low histeresys level. [ADC_units] */
#define OVPWR_LIM_HYST     		(237860)//(137860)//(237860) //(178390) // Aprox. 15W
/** Slow down of Vout reference modification when in same direction by constant power control loop. */    
#define OVP_VOUT_DLY			(2)  
/** Constant power control loop execution frequency division. */
#define OVP_VOUT_PRSCLR			(4)  
/** Constant power control loop execution frequency division during soft start. */
#define OVP_VOUT_PRSCLR_STRP	(0)
/** Size of step change of Vout reference during soft start by constant power loop. */
#define OVP_VOUT_STEP_STRP		(4)
/** Over current hiccup detection filter. [control_cyc] */
#define OVCRR_HICCUP_IN_CNT_LIM	(15)
/** Over power hiccup detection filter. 300 seconds. [control_cyc] */
#define OVPWR_HICCUP_IN_CNT_LIM	(250000)
/** Proportional factor of constant power loop. */
#define OVP_P_DEC_FCTR			(12)
/** Proportional factor of constant power loop. */
#define OVP_P_INC_FCTR			(19)

/** Current limit in normal mode for entering HICCUP with a delay. [ADC_units] */
#define BOOST_HICCUP_DLYD_LIM  	(3100) // Aprox. 68 A
/** Current limit during soft start for entering HICCUP mode. [ADC_units] */
#define BOOST_HICCUP_SOFT_LIM   (1000)
/** Current limit in normal mode for entering HICCUP. [ADC_units] */
#define BOOST_HICCUP_LIM        (3100) // Aprox. 68 A
/** Hiccup detection filter. [control_cyc] */
#define BOOST_HICCUP_IN_CNT_LIM (25)
/** Over power hiccup detection filter. 30 seconds. [control_cyc] */
#define DLYD_HICCUP_IN_CNT_LIM	(25000)
/** Constant power control loop execution frequency division. */
#define DLYD_HICCUP_PRSCLR		(4) 
/** @} */

/**
 * \name DCM Discontinuous conduction mode
 * Secondary side discontinuous conduction mode. Not safe to keep synchronous ON.
 * @{
 */
/** Hysteresis of DCM detection. [ADC_units] */
#define DCM_HYSTE			(90)
/** Current limit for DCM entry detection. Approximately 13 A. [ADC_units] */
#define DCM_ENTER_LIM       (parameters_RAM.synch_DCM)
/** Current limit for DCM exit detection. Approximately 15 A. [ADC_units] */
#define DCM_EXIT_LIM        (DCM_ENTER_LIM + DCM_HYSTE)
/** DCM entry condition filter. [control_cyc] */
#define DCM_IN_CNT_LIM      (1)
/** DCM exit condition filter. [control_cyc] */
#define DCM_OUT_CNT_LIM     (15)
/** Synchronous active after trap delay cycles. [control_cyc] */
#define SYNCH_ON_CNT     	(0)
/** @} */

/**
 * \name ICP Inverse current protection
 * Synchronous deactivated, pure diodes mode.
 * @{
 */
/** Hysteresis of ICP detection. [ADC_units] */
#define ICP_HYSTE			(92)
/** Current limit for ICP entry detection. Approximately 4 A. [ADC_units] */
#define ICP_ENTER_LIM       (parameters_RAM.synch_ICP)
/** Current limit for DCM entry detection. Approximately 5 A. [ADC_units] */
#define ICP_EXIT_LIM        (ICP_ENTER_LIM + ICP_HYSTE)
/** @} */

/**
 * \name UVP Output under voltage protection
 * Output voltage in range protection. There is a window of valid output voltage 
 * after soft-start.
 * @{
 */
/** Output under voltage protection IRQ number */
#define UVP_IRQ_N       23
#define uvp_irq         IRQ_Hdlr_23
/** Under voltage protection limit. Top of scale is 1024. [ADC_units] */
#define VOLTAGE_UVP     (500) //(578) Aprox 30V
#define XMC_VADC_RESULT_LEFT_ALIGN_10BIT (2U)
/** Activates fast output under voltage protection. */
#define UVP_ON()        {NVIC_ClearPendingIRQ(UVP_IRQ_N); \
						 NVIC_EnableIRQ(UVP_IRQ_N);}
/** Deactivates fast output under voltage protection. */
#define UVP_OFF()       {NVIC_DisableIRQ(UVP_IRQ_N);}
/** @} */

/**
 * \name NTC Temperature control
 * Control of fan speed and temperature warnings.
 * @{
 */
#define NTC_55_DEG				(2300) // NTC_85_DEG Aprox 750ADC
/** Power of 2 close to the maximum expected value of output current. [bits] */
#define FAN_NTC_RATIO    		(12) // Is using filtering, then the values are shifted to the left.
/** Multiplier to scalate fan speed related to Io. [units] */
#define FAN_NTC_FACTOR          (8000) // Aprox: (FAN_PWM_MAX - FAN_PWM_MIN) * (1 << IL_FAN_RATIO) / (NTC_35_DEG - NTC_95_DEG)
/** Minimum number of tachometer pulses to be detected. [rising_edge] */
#define FAN_MIN_TCH_PULSES		(50)
/** Power of 2 close to the maximum expected value of output current. [bits] */
#define FAN_IL_RATIO    		(12) // Is using filtering, then the values are shifted to the left.
#define FAN_IL_OFFST			(200)
/** Multiplier to scalate fan speed related to Io. [units] */
#define FAN_IL_FACTOR          	(6000) // Aprox: (FAN_PWM_MAX - FAN_PWM_MIN) * (1 << IL_FAN_RATIO) / MAX_IO
/** Maximum Fan speed. [CCU_clock] */
#define FAN_PWM_MAX             (3050)
/** Minimum Fan speed. [CCU_clock] */
#define FAN_PWM_MIN             (350)
/** Power of 2 close to the maximum temperature range possible. [bits] */
#define NTC_MAX_BITS            (13)
/** Temperature warning limit. [ADC_units] */
#define NTC_TEMP_ALERT          (999) // Aprox 85 °C
/** Over temperature limit. [ADC_units] */
#define NTC_TEMP_LATCH          (642) // Aprox 100 °C
/** Over temperature condition filter. [control_cyc] */
#define OVER_TEMP_IN_CNT_LIM    (10)
/** Clock division of fan tachometer checking frequency. [power of 2] */
#define FAN_TACHO_CLK_DIV		(6)
#define FAN_DEC_SPEED_DIV		(2)
/** @} */

/**
 * \name OVP Output over voltage protection
 * Redundant output voltage in range protection. 
 * @{
 */
/** Output over voltage protection IRQ number */
#define OVP_IRQ_N       	20
#define ovp_irq         	IRQ_Hdlr_20
/** Over voltage protection threshold. Around 60V. [ADC_units] */
#define VOLTAGE_OVP     	(0xF85) // Aprox. 60V
/** Activates over voltage protection. */
#define OVP_ON()        	{NVIC_ClearPendingIRQ(OVP_IRQ_N); \
                         	 NVIC_EnableIRQ(OVP_IRQ_N);}
/** Deactivates over voltage protection. */
#define OVP_OFF()       	{NVIC_DisableIRQ(OVP_IRQ_N);}

/** Output over voltage protection IRQ number */
#define BOOST_OVP_IRQ_N     24
#define boost_ovp_irq       IRQ_Hdlr_24
/** Over voltage protection threshold. Around 451V. [ADC_units] */
#define BOOST_VOLTAGE_OVP	(3690)//(3438)//(3615) // Aprox. 410V Note: BOOST_VIN_MAX / 3
/** Under voltage protection threshold. Around 451V. [ADC_units] */
#define BOOST_VOLTAGE_UVP	(3261)//(3100)-->360v//(3261) -->升压为380V时//(3438) // Aprox. 390V Note: BOOST_VIN_MIN / 3
/** Activates over voltage protection. */
#define BOOST_OVP_ON()      {NVIC_ClearPendingIRQ(BOOST_OVP_IRQ_N); \
                         	 NVIC_EnableIRQ(BOOST_OVP_IRQ_N);}
/** Deactivates over voltage protection. */
#define BOOST_OVP_OFF()     {NVIC_DisableIRQ(BOOST_OVP_IRQ_N);}
/** @} */

/**
 * \name Startup
 * Soft start procedure configuration
 * @{
 */
/** Control loop IRQ number */
#define HIGH_FRQ_IRQ_N      			19
#define high_freq_irq       			IRQ_Hdlr_19
/** Soft start-up reference step increment. [ADC_units] */
#define BUCK_START_UP_INC       		(24)
/** Soft start-up reference step increment. [ADC_units] */
#define START_UP_LOW_INC    			(10)
/** Soft start-up reference step adaptive delay. [ADC_units] */
#define START_UP_INC_CNT				(20)
/** Soft start-up increment threshold. [ADC_units] */
#define START_UP_LOW_THRSHLD 			(600)
/** Soft start-up maximum step time. [control_cyc] */
#define BUCK_START_UP_STEP_TIME			(10)
/** Start up initial reference value. [ADC_units] */
/* Important: never less than 1. Protection against overvoltage at the start. */
#define START_UP_INIT       			(10)

/** Soft start-up reference step increment. [ADC_units] */
#define BOOST_START_UP_INC     			(1)
/** Soft start-up maximum step time. [control_cyc] */
#define BOOST_START_UP_STEP_TIME  		(750)
/** Maximum additional starting duty to apply in function of battery voltage. [CCU_clk] */
#define BOOST_SOFT_STRT_DUTY_INIT		(82)    
/** Maximum overall additional duty to apply at the first pulses of start up. [CCU_clk] */
#define BOOST_SOFT_STRT_DUTY_INIT_MAX	(110)

/** Activates control loop interrupt. */
#define COMPENSATOR_ON()    		{NVIC_EnableIRQ(HIGH_FRQ_IRQ_N); \
									 OVP_ON(); \
									 BOOST_OVP_ON();}
/** @} */
/** @} */

/**
 * \name Controller structures
 * @{
 */
/** Voltage buck controller */
typedef struct
{
	uint16_t reference; /**< Voltage reference. [Q0] */
	int32_t error[2]; /**< Voltage error buffer. [Q0] */
	int32_t phase[2]; /**< Control output buffer. [Q0.Q_DECIMALS] */
	uint16_t phase_out; /**< Control output. [Q0] */
    uint16_t min_phase; /**< Minimum allowed phase shift. [CCU_clock] */
    uint16_t burst_phase; /**< Minimum shift during burst mode. */
    uint16_t blk_phase; /**< Blanking value used to regulate during soft start. [CCU_clock] */
    uint16_t burst_stop_limit; /**< Under this shift the PWM is trapped. [CCU_clock] */
    uint16_t burst_low_limit; /**< Under this shift the burst mode starts. [CCU_clock] */
    uint16_t burst_high_limit; /**< Over this shift the busrt mode stops. [CCU_clock] */
	uint16_t start_up_cnt; /**< Timer for start up steps. [control_cyc] */
	uint16_t reference_startup; /**< Voltage reference under power limitation. [ADC units] */
	uint16_t soft_start_inc; /**< Step increment during soft-start. [ADC units] */
} voltage_ctr_t;

/** Voltage boost controller */
typedef struct
{
	uint16_t reference; /**< Voltage reference. [Q0] */
	int32_t error[2]; /**< Voltage error buffer. [Q0] */
	int32_t duty[2]; /**< Control output buffer. [Q0.Q_DECIMALS] */
	uint16_t hr_phase_out; /** High resolution control output. [Q0] */
	int16_t duty_out; /**< Control output. [Q0] */
    uint16_t min_duty; /**< Minimum allowed phase shift. [CCU_clock] */
    uint16_t burst_duty; /**< Minimum shift during burst mode. */
    int16_t burst_stop_thrshld; /**< Vout under this threshold resumes normal mode. [CCU_clock] */
    int16_t burst_high_thrshld; /**< Vout over this threshold starts burst mode. [CCU_clock] */
    int16_t burst_low_thrshld; /**< Vout under this threshold starts a PWM burst. [CCU_clock] */
	uint16_t start_up_cnt; /**< Timer for start up steps. [control_cyc] */
	uint16_t sync_strp_ovrlp; /**< Overlap of synchronous during startup. [control_cyc] */
} voltage_boost_ctr_t;

/** Current controller */
typedef struct
{
    uint32_t adc_il_measure; /**< Input current measurement. Its only updated once during a control loop iteration. See ADC_IL_RESULT. [ADC units] */
    uint32_t adc_io_measure; /**< Input current measurement. Its only updated once during a control loop iteration. See ADC_IL_RESULT. [ADC units] */
    uint32_t adc_io_zero; /**< Input current measurement. Its only updated once during a control loop iteration. See ADC_IL_RESULT. [ADC units] */
    uint32_t hiccup_io_limit; /**< Over current protection limit adjusted in relation to the input voltage. [ADC units] */
    uint16_t dt_A_B; /**< Dead times of the AB leg adjusted in relation to the input current. [CCU clock] */
    uint16_t dt_C_D; /**< Dead times of the CD leg adjusted in relation to the input current. [CCU clock] */
    uint16_t synch_il_ON; /**< Displacement of the ON edge of the synchr. because of the current. [CCU clock] */
    uint16_t synch_il_OFF; /**< Displacement of the OFF edge of the synchr. because of the current. [CCU clock] */
    uint16_t ovp_state; /**< Output over power exceeding limit time. [Bool] */
} current_ctr_t;

/** Possible fault states. Lower 16 bits status flags, higher 16 bits faults flags. */
typedef enum
{
    /* States */
    OK = 			0x0000, /**< No fault. */
    DCM = 			0x0001, /**< Discontinuous conduction mode condition in secondary side. */
    BURST = 		0x0002, /**< Burst mode active. */
    SOFT = 			0x0004, /**< Soft start sequence active. */
    START = 		0x0008, /**< Start requested from communication interface. */
    STOP = 			0x0010, /**< Stop request from communication interface. */
    START_EN = 		0x0040, /**< Converter enabled. */
    TEMP_WARNING = 	0x0080, /**< Temperature warning condition. */
	BOOST_MODE =	0x0100, /**< Converter in boost discharge mode. */
	TRAPPING = 		0x0200, /**< Converter trapping PWM. Requires decreasing duty before. */
	SYNC_ICP = 		(0xFFFFFFFF & ~(DCM | START_EN | TEMP_WARNING)), /**< Mask for synchronous driving allowed. */
    SYNC_OFF = 		(0xFFFFFFFF & ~(BOOST_MODE | DCM | START_EN | TEMP_WARNING | BURST)), /**< Mask for synchronous driving allowed. */
    /* Failures */
    HICCUP_FAIL = 	0x00010000, /**< Fault: output over current protection. */
    UV_FAIL = 		0x00020000, /**< Fault: output under voltage protection. */
    OFF = 			0x00040000, /**< Fault: converter switched OFF or fault detected. */
    START_FAIL = 	0x00080000, /**< Fault: soft start time out protection. */
    FAN_FAIL = 		0x00100000, /**< Fault: fan blocked protection. */
    VIN_FAIL = 		0x00200000, /**< Fault: input voltage out of range. */
    TEMP_FAIL = 	0x00400000 /**< Fault: over temperature protection. */
} zvs_status_t;

/** Mask for faults in the converter state. High half word. */
#define STATUS_FAULT 0xFFFF0000
/** Mask for modes in the converter state. Low half word. */
#define STATUS_STATE 0x0000FFFF

/** Converter measurements */
typedef struct
{
	uint32_t time_tick; /**< Tick counter at the frequency of the voltage controller. [control_cyc] */
    uint32_t adc_vin_measure; /**< Input voltage measurement. Its only updated once during a iteration. See ADC_VIN_RESULT. [ADC_units] */
    uint32_t adc_vout_measure; /**< Output voltage measurement. Its only updated once during a iteration. See ADC_VOUT_RESULT. [ADC_units] */
    zvs_status_t status; /**< Converter status. Lower 16 bits status bits, higher 16 bits faults. */
    uint16_t store_params; /**< Storage of parameters request. */
    uint16_t ntc_temperature; /**< NTC temperature. [ADC_units]. */
    uint16_t die_temperature; /**< Die temperature. [ADC_units]. */
} converter_ctr_t;

/** Voltage buck controller instance. */
volatile voltage_ctr_t voltage_ctr;
/** Voltage boost controller instance. */
volatile voltage_boost_ctr_t voltage_boost_ctr;
/** Current controller instance. */
volatile current_ctr_t current_ctr;
/** Converter measures instance. */
volatile converter_ctr_t converter_ctr;
/** @} */

/*---------------------------------------------------------------------------*/
/**
 * \brief       Dead time adjustment
 * \return      None
 *
 * Dead times adjusted in relation to the output current.
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void pwm_dt_adjust()
{
	/* Updates and the dead times. Shadow enable request might be done outside. */
	PWM_A_B.hrc_slice_ptr->SDCR = current_ctr.dt_A_B;
	PWM_A_B.hrc_slice_ptr->SDCF = current_ctr.dt_A_B;
	PWM_C.hrc_slice_ptr->SDCR = current_ctr.dt_C_D;
	PWM_D.hrc_slice_ptr->SDCR = current_ctr.dt_C_D;
}
/*---------------------------------------------------------------------------*/
/**
 * \brief	Turn OFF converter
 * \return	None
 */
#ifndef DOXYGEN_SKIP
__attribute__((section(".ram_code")))
#endif
static inline void converter_set_off()
{
    /* Deactivate under voltage protection, the voltage is going to fall down. */
    UVP_OFF();
    XMC_VADC_GROUP_SetBoundaries(VADC_G0, 0, VOLTAGE_OVP);
    /* Set converter as OFF. */
    converter_ctr.status |= OFF;
    converter_ctr.status &= ~STOP;
    /* Deactivate all PWM signals. */
    if(converter_ctr.status & BOOST_MODE)
    {
    	/* Turning off sequence required in boost mode. */
    	converter_ctr.status |= TRAPPING;
    	XMC_VADC_GROUP_SetBoundaries(VADC_G1, 0, BOOST_VOLTAGE_OVP);
    }
    else
    {
        TRAP_SET();
    }
}

/*---------------------------------------------------------------------------*/
uint8_t buck_mode_set; /**< Activation of buck mode from boost mode requires waiting for the turn OFF transition. */
void voltage_ctr_init();
void current_ctr_init();
void low_priority_task();

#endif /* __CONTROLLER_H_ */
/** @} */
